#include "queue.h"
#include "util_errno.h"

/**
 * \brief	初始化队列入口，这时候整个队列是空的
 */
void queue_entry_init(queue_entry_t *pqe)
{
	if (!pqe)
		return;

	queue_lock_init(&(pqe->lock));

	queue_lock(&(pqe->lock));
	for (int i = 0; i < QUEUE_MEMBER_MAX; i++) {
		init_list_head(&(pqe->lists[i]));
	}
	queue_unlock(&(pqe->lock));
}

/**
 * \brief	初始化一个队列中的元素
 */
void queue_init(queue_t *pq)
{
	if (!pq)
		return;

	init_list_head(&(pq->node));
	pq->queue_entry = NULL;
}

/**
 * \brief	将队列元素释放到其它队列或自己队列的已使用入口或已释放入口
 * \param	line:	QUEUE_USED or QUEUE_FREE
 */
int queue_put(queue_entry_t *pqe, queue_t *pq, int line)
{
	list_head_t *node, *head;

	if (!pq || line >= QUEUE_MEMBER_MAX)
		return -EPERM;

	if (!pqe)
		pqe = pq->queue_entry;
	if (!pqe)
		return -EPERM;

	queue_lock(&(pqe->lock));

	node = &(pq->node);			/* 当前队列节点 */
	head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */

	list_del_init(node);		/* 删除node原来的链表，并重新初始化node这个链表 */
	list_add_tail(node, head);	/* 加到链表尾，先入先出 */

	queue_unlock(&(pqe->lock));

	return 0;

}

/**
 * \brief	从队列入口的已使用入口或已释放入口获取一个队列元素
 * \param	line:	QUEUE_USED or QUEUE_FREE
 */
queue_t *queue_get(queue_entry_t *pqe, int line)
{
	queue_t *pq;
	list_head_t *node, *head;

	if (!pqe || line >= QUEUE_MEMBER_MAX)
		return NULL;

	queue_lock(&(pqe->lock));

	head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */

	pq = NULL;
	if (!list_empty_careful(head)) {
		pq = list_first_entry(head, queue_t, node);	/* 获取队列的第一个元素 */
		node = &(pq->node);
		list_del_init(node);	/* 销毁该元素 */
	}

	queue_unlock(&(pqe->lock));

	return pq;
}

/**
 * \brief	预览已使用或者已释放队列中的第一个元素
 * \details	该元素预览后不会被弹出
 * \param	line:	QUEUE_USED or QUEUE_FREE
 */
queue_t *queue_peek(queue_entry_t *pqe, int line)
{
	queue_t *pq;
	list_head_t *head;

	if (!pqe || line >= QUEUE_MEMBER_MAX)
		return NULL;

	queue_lock(&(pqe->lock));

	head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */

	pq = NULL;
	if (!list_empty_careful(head)) {
		pq = list_first_entry(head, queue_t, node);	/* 获取队列的第一个元素 */
	}

	queue_unlock(&(pqe->lock));

	return pq;
}

/**
 * \brief	获取已使用或者已释放队列中剩余的元素个数
 * \param	line:	QUEUE_USED or QUEUE_FREE
 */
int queue_count(queue_entry_t *pqe, int line)
{
	int count = 0;
	list_head_t *node, *n, *head;

	if (!pqe || line >= QUEUE_MEMBER_MAX)
		return -EPERM;

	queue_lock(&(pqe->lock));

	head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */

	if (!list_empty_careful(head)) {
		list_for_each_safe(node, n, head) {
			count++;
		}
	}

	queue_unlock(&(pqe->lock));

	return count;
}
